//Test program for simple constant propagation

#include <stdio.h>
#define WriteLine() printf("\n");
#define WriteLong(x) printf(" %lld", (long)x);
#define ReadLong(a) if (fscanf(stdin, "%lld", &a) != 1) a = 0;
#define long long long

long a, b, z;

void check_global(){
	a = 5;
}

void main()
{
	long c;
	long d;
	long e;
	long i;
	long j;

	c = 1;
	d = c;	//Obviously should propagate

	WriteLong(d);
	WriteLine();

	c = 10;
	d = c + 5; //should propagate

	WriteLong(d);
	WriteLine();

	c = 20;

	//Different block with a definition of c, but its still the same constant
	if(10 == 10){
		c = 20;
	}

	d = c + 10;//Should propagate c = 20 here, since both preceeding blocks have the same definition of c

	WriteLong(d);
	WriteLine();

	c = 30;

	if(1 == 1){
		c = 20;
	}

	d = c + 15;//Should not propagate here, since the two merging preceeding blocks have different values for c

	WriteLong(d);
	WriteLine();
	
	c = d + 20;//Should not propagate here, since d is not a constant

	WriteLong(c);
	WriteLine();
	
	c = 100;
	i = 1;
	j = 1;
	while(i <= 10){
		d = c; //Should propagate here
		while(j <= 10){
			d = c; //Should propagate here
			j = j + 1;
		}
		i = i + 1;
	}
	
	c = d; //Shouldn't propagate here - what if we didn't go through the loop?
	WriteLong(c);
	WriteLine();

	//Do the same for the globals
	a = 1;
	b = a;
	WriteLong(b);
	WriteLine();
	
	a = 10;
	b = a + 5; //this should propagate
	WriteLong(b);
	WriteLine();

	a = 20;
	//Different block with a definition of a, but its still the same constant
	if(10 == 10){
		a = 20;
	}
	b = a + 10;//Should propagate a = 20 here, since both preceeding blocks have the same definition of a
	WriteLong(b);
	WriteLine();

	a = 30;
	if(1 == 1){
		a = 20;
	}
	b = a + 15;//Should not propagate here, since the two merging preceeding blocks have different values for a
	WriteLong(b);
	WriteLine();
	
	a = b + 20;//Should not propagate here, since b is not a constant
	WriteLong(a);
	WriteLine();

	a = 100;
	i = 1;
	j = 1;
	while(i <= 10){
		b = a; //Should propagate here
		while(j <= 10){
			b = a; //Should propagate here
			j = j + 1;
		}
		i = i + 1;
	}
	
	a = b; //Shouldn't propagate here - what if we didn't go through the loop?
	WriteLong(a);
	WriteLine();

	a = 20;
	check_global();
	b = a; // Shouldn't propagate here - a function call kills all global definitions, since we don't know how the function modifies them

	WriteLong(b);
	WriteLine();

	i = 1;
	//should not propagate here in this loop
	while(i <= 10){
		b = i;
		i = i + 1;
	}

	WriteLong(b);
	WriteLine();
}

/*Total propagations: 5
Expected output:
 1
 15
 30
 35
 55
 100
 1
 15
 30
 35
 55
 100
 5
 10
*/